#pragma once
#include "CurrentThread.h"
#include "Noncopyable.h"
#include "Timestamp.h"
#include <atomic>
#include <functional>
#include <memory>
#include <mutex>
#include <vector>

class Channel;
class Poller;
// 事件循环类，主要包括两个大模块 Channel 和 Poller
class EventLoop : Noncopyable
{
  public:
    using Functor = std::function<void()>;
    EventLoop();
    ~EventLoop();

    void loop(); // 开启事件循环
    void quit(); // 退出事件循环

    Timestamp pollReturnTime() const
    {
        return pollReturnTime_;
    }
    void runInLoop(Functor cb); // 在当前loop中执行
    void queueInLoop(Functor cb); // 把cb放入loop,唤醒loop所在的线程，执行cb

    void wakeup(); // mainLoop来唤醒subLoop
    // 调用poller的方法来实现
    void updateChannel(Channel *channel);
    void removeChannel(Channel *channel);
    bool hasChannel(Channel *channel);

    // 判断当前loop是否在自己的线程里面
    bool isInLoopThread() const
    {
        return threadId_ == CurrentThread::tid();
    }

  private:
    void handleRead();
    void doPendingFunctors();

    using ChannelList = std::vector<Channel *>;

    std::atomic_bool looping_; // 标志是否正在循环
    std::atomic_bool quit_;    // 标志退出loop循环
    std::atomic_bool
        callingPendingFunctors_; // 标志当前loop是否有需要执行的回调操作
    const pid_t threadId_;

    Timestamp pollReturnTime_; // poller返回发生事件的channels的事件的时间点
    std::unique_ptr<Poller> poller_;

    int wakeupFd_; // 当mainLoop获取一个新用户channel时，通过轮询算法选一个subLoop,
                   // wakeupFd_用来把subLoop从epoll_wait中唤醒
    std::unique_ptr<Channel> wakeupChannel_;

    ChannelList activeChannels_;

    std::vector<Functor> pendingFunctors_; // 存储loop需要执行的所有回调操作
    std::mutex mutex_;                     // 保护vector的线程安全

}; // class EventLoop
